#include <iostream>
#include <string>
#include <typeinfo>
#include <utility>
// #include <any>


class Any
{
public:
    class holder
    {
    public:
        virtual ~holder()
        {}
        virtual const std::type_info& type() = 0;  //获取当前子类的数据类型 -- 返回类型是const type_info&
        virtual holder* clone() = 0;        //针对当前的对象自身，克隆出一个新的子类对象
    };

    template<class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T& val = T()):_val(val)
        {}
        virtual const std::type_info& type()
        {
            return typeid(T);
        }
        virtual holder* clone()
        {
            return new placeholder(_val);
        }
        T _val;     //主要是这里，如果不通过virtual，则无法释放这里的对象
    };

    Any():_content(NULL)
    {}
    template <class T>
    Any(const T& content):_content(new placeholder<T>(content))
    {}
    ~Any()
    {
        delete _content;
    }
    Any& swap(Any& other)
    {
        std::swap(_content, other._content);
        return *this;
    }
    template<class T>
    Any& operator=(const T& val)
    {
        Any(val).swap(*this);   //这样写的好处：Any(val)为临时对象，交换完生命周期就到了，就会调用自己的析构函数
        return *this;
    }
    Any& operator=(const Any& other)
    {
        Any(other).swap(*this);
        return *this;
    }

    template<class T>
    T* get()    //返回子类对象保存数据的指针
    {
        if (typeid(T) != _content->type())  //如果你要的类型和我保存的类型不匹配
            return NULL;
        return &(((placeholder<T>*)_content)->_val);
    }
public:
    holder* _content;
};

class Test
{
public:
    Test()
    {
        std::cout << "Test()" << std::endl;
    }
    Test(const Test& t)
    {
        std::cout << "Test()" << std::endl;
    }
    ~Test()
    {
        std::cout << "~Test()" << std::endl;
    }
};

int main()
{
    // //官方any的使用方法，主要还是要查文档
    // std::any a;
    // a = 10;
    // int* pi = std::any_cast<int>(&a);
    // std::cout << *pi << std::endl;

    // a = std::string("hello");
    // std::string* ps = std::any_cast<std::string>(&a);
    // std::cout << *ps << std::endl;

    Any a;
    {
        Test t;
        a = t;
    }
    a = 10;
    
    int *pa = a.get<int>();
    std::cout << *pa << std::endl;
    a = std::string("nihao");
    std::string *ps = a.get<std::string>();
    std::cout << *ps << std::endl;
    return 0;
}